package com.sxw.jwt;

import com.alibaba.fastjson2.JSONObject;
import com.sxw.dto.PlayerSessionDto;
import com.sxw.utils.JwtTokenProvider;
import com.sxw.utils.RedisUtils;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;
import org.springframework.lang.NonNull;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.ArrayList;


@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
    private final RedisUtils redisUtils;
    private final JwtTokenProvider tokenProvider;
    public JwtAuthenticationFilter(RedisUtils redisUtils, JwtTokenProvider tokenProvider) {
        this.redisUtils = redisUtils;
        this.tokenProvider = tokenProvider;
    }

    @Override
    protected void doFilterInternal(@NonNull HttpServletRequest request,
                                    @NonNull HttpServletResponse response,
                                    @NonNull FilterChain filterChain) throws ServletException, IOException {

        try {
            String token = getTokenFromRequest(request);

            if (StringUtils.hasText(token) && tokenProvider.validateToken(token)) {
                String username = tokenProvider.getUsernameFromToken(token);

                // 根据不同的登录类型，构建相应的Redis键
                // 注意：在实际项目中，我们需要能够确定用户的登录类型来正确构建键
                String redisKey = "player:session:" + username;
                // 尝试不同类型的键来查找会话
                Object o = redisUtils.get(redisKey);
                PlayerSessionDto playerSession = null;
                if (o != null) {
                    playerSession = JSONObject.parseObject(o.toString(), PlayerSessionDto.class);
                }
                if (playerSession == null) {
                    // Redis中不存在，说明Session已过期，或已被强制下线
                    filterChain.doFilter(request, response);
                }else {
                    // 更新Session活跃时间，防止过期
                    playerSession.setLastActiveTime(System.currentTimeMillis());
                    redisUtils.set(redisKey, JSONObject.toJSONString(playerSession), 1800);
                    request.setAttribute("userName", username);
                    request.setAttribute("player_session", playerSession);
                    // 创建认证对象
                    UsernamePasswordAuthenticationToken authentication =
                            new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>());
                    authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    // 设置认证信息到 SecurityContext
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }
            }
        } catch (Exception ex) {
            logger.error("无法设置用户认证", ex);
        }

        filterChain.doFilter(request, response);
    }

    private String getTokenFromRequest(HttpServletRequest request) {
        // 从 Authorization header 获取 token
        String bearerToken = request.getHeader("Authorization");
        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        return null;
    }

}